package com.xhtt.modules.reportform.service.impl;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhtt.common.exception.RRException;
import com.xhtt.common.exception.RRExceptionEnum;
import com.xhtt.common.utils.*;
import com.xhtt.modules.inspection.enums.InsResult;
import com.xhtt.modules.inspection.enums.InspectTypeEnum;
import com.xhtt.modules.inspection.enums.ShiftTypeEnum;
import com.xhtt.modules.inspection.service.IInsClassesTeamDetailService;
import com.xhtt.modules.inspection.service.IInsTaskStepService;
import com.xhtt.modules.inspection.service.IInsTaskUserService;
import com.xhtt.modules.reportform.dao.InsReportMapper;
import com.xhtt.modules.reportform.model.InsEveryTeamReport;
import com.xhtt.modules.reportform.model.InsEveryoneReport;
import com.xhtt.modules.reportform.service.InsReportService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 统计分析-现场巡检
 * </p>
 *
 * @author xj
 * @since 2019-02-14
 */
@Service
public class InsReportServiceImpl extends ServiceImpl<InsReportMapper, InsEveryoneReport> implements InsReportService {

    @Autowired
    private IInsClassesTeamDetailService insClassesTeamDetailService;

    @Autowired
    private IInsTaskUserService insTaskUserService;

    @Autowired
    private IInsTaskStepService insTaskStepService;

    private final DateTimeFormatter tf = DateTimeFormatter.ofPattern("HH:mm");

    @Override
    public PageUtils queryInsEveryone(Map<String, Object> params) {

        Page<InsEveryoneReport> page = new Query<InsEveryoneReport>(params).getPage();

        List<InsEveryoneReport> inspectionReportEntities = baseMapper.queryInsEveryone(page, params);

        inspectionReportEntities.forEach(e -> {

            // 分钟转化小时
            if (Optional.ofNullable(e.getMinutes()).isPresent()) {
                e.setMinuteStr(minute2hourStr(e.getMinutes(), false));
            }

            // 巡检开始时间
            String insStartDate = null;
            String weekAndMonthStartTime = null; // 周巡检和月巡检巡检开始时间
            if (e.getInsStartDate() != null) {
                insStartDate = DateUtils.df.format(e.getInsStartDate());
                weekAndMonthStartTime = tf.format(e.getInsStartDate());
            }
            // 巡检结束时间
            String insEndDate = null;
            String weekAndMonthEndTime = null;   // 周巡检和月巡检巡检结束时间
            if (e.getInsEndDate() != null) {
                insEndDate = DateUtils.df.format(e.getInsEndDate());
                weekAndMonthEndTime = tf.format(e.getInsEndDate());
            }
            // 日班开始时间
            String insMorningStart = null;
            if (e.getInspectMorningStartDate() != null) {
                insMorningStart = tf.format(e.getInspectMorningStartDate());
            }
            // 日班结束时间
            String insMorningEnd = null;
            if (e.getInspectMorningEndDate() != null) {
                insMorningEnd = tf.format(e.getInspectMorningEndDate());
            }
            // 夜班开始时间
            String insNightStart = null;
            if (e.getInspectNightStartDate() != null) {
                insNightStart = tf.format(e.getInspectNightStartDate());
            }
            // 夜班结束时间
            String insNightEnd = null;
            if (e.getInspectNightEndDate() != null) {
                insNightEnd = tf.format(e.getInspectNightEndDate());
            }

            /*
             * 非日巡检查找排班情况
             * 并且设置任务时间为巡检结束时间
             */
            if (!e.getInspectType().equals(InspectTypeEnum.DAY.getCode())) {
                // 巡检结束时间
                LocalDateTime resultDate = e.getInsEndDate();
                Integer shiftType = insClassesTeamDetailService.getShiftTypeByDate(resultDate, e.getTeamId());
                e.setShiftType(shiftType);

                // 时间设置为任务结束的那一天
                e.setStartDate(e.getInsStartDate());
                // 能查询到的周巡检和月巡检都是已完成的
                e.setResult(InsResult.FINISHED);
                e.setTime(weekAndMonthStartTime + "-" + weekAndMonthEndTime);
            } else {
                // 设置巡检时间段
                if (e.getShiftType().equals(ShiftTypeEnum.DAY.getCode())) {
                    e.setTime(insMorningStart + "-" + insMorningEnd);
                    e.setRealEndTime(e.getInspectMorningEndDate());
                } else if (e.getShiftType().equals(ShiftTypeEnum.NIGHT.getCode())) {
                    e.setTime(insNightStart + "-" + insNightEnd);
                    e.setRealEndTime(e.getInspectNightEndDate());
                }
            }
            // 设置排班情况
            e.setShiftName(EnumUtils.getMsgByCode(ShiftTypeEnum.class, e.getShiftType()).getMsg());
            // 设置巡检结果 根据巡检开始和结束时间判断
            if (StringUtils.isEmpty(insStartDate) && StringUtils.isEmpty(insEndDate)) {
                // 设置巡检人员,未巡检则设置发布任务时选择的人员
//                Integer taskId = e.getTaskId();
//                String executor = e.getExecutor();
//                if (StringUtils.isEmpty(executor)) {
//                    String name = insTaskUserService.getUserByTaskIdAndDate(taskId, e.getStartDate());
//                    e.setExecutor(name);
//                }
                e.setExecutor("--");
                e.setResult(InsResult.NOT_START);
                // 周巡检和月巡检如果是未巡检，将时间设置为当月/周的最后一天
                if (!e.getInspectType().equals(InspectTypeEnum.DAY.getCode())) {
                    e.setStartDate(e.getEndDate());
                }
            } else if (StringUtils.isNotEmpty(insStartDate) && StringUtils.isEmpty(insEndDate)) {
                e.setResult(InsResult.NOT_FINISH);
            } else if (StringUtils.isNotEmpty(insStartDate) && StringUtils.isNotEmpty(insEndDate)) {
                if (e.getRealEndTime() != null) {
                    if (e.getInsEndDate().isAfter(e.getRealEndTime())) {
                        e.setResult(InsResult.DELAYED);
                    } else {
                        e.setResult(InsResult.FINISHED);
                    }
                }
            }

        });

        // 重新排序
        inspectionReportEntities = inspectionReportEntities.stream()
                .sorted(Comparator.comparing(InsEveryoneReport::getStartDate).reversed()).collect(Collectors.toList());
        page.setRecords(inspectionReportEntities);

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryInsEveryTeam(Map<String, Object> params) {

        Page<InsEveryTeamReport> page = new Query<InsEveryTeamReport>(params).getPage();

        List<InsEveryTeamReport> insEveryTeamReports = baseMapper.queryInsEveryTeam(page, params);

        insEveryTeamReports.forEach(e -> {

            // 分钟转化小时
            if (Optional.ofNullable(e.getMinutes()).isPresent()) {
                e.setMinuteStr(minute2hourStr(e.getMinutes(), false));
            } else {
                e.setMinuteStr(minute2hourStr(0, false));
            }

            int totalCount = e.getTotalCount();

            int finishCount = e.getFinishCount();

            int delayCount = e.getDelayCount();

            int noStartCount = e.getNoStartCount();

            String shiftName = e.getShiftName();
            if (StringUtils.isEmpty(shiftName)) {
                e.setShiftName("--");
            }

            // 11 正常完成 12 未完成 13 未巡检
            Integer status = e.getStatus();

            // 周/月巡检通过status即可判断巡检状态
            // 日巡检需要根据"已完成","未完成","延期","总条数"来判断
            if (status.equals(11)) {
                e.setResult(InsResult.FINISHED);
            } else if (status.equals(12)) {
                e.setResult(InsResult.NOT_FINISH);
            } else {
                if (totalCount > 0) {
                    if (finishCount >= totalCount) {
                        if (delayCount > 0) {
                            e.setResult(InsResult.DELAYED);
                        } else {
                            e.setResult(InsResult.FINISHED);
                        }
                    } else {
                        e.setResult(InsResult.NOT_FINISH);
                    }
                }
            }

        });

        page.setRecords(insEveryTeamReports);
        return new PageUtils(page);
    }


    @Override
    public void exportEveryone(HttpServletResponse response, Map<String, Object> params) {


        ExportExcel exportExcel = new ExportExcel();

        params.put("limit", "10000000");

        PageUtils pageUtils = queryInsEveryone(params);
        List list = pageUtils.getList();
        String fileName = "每人巡检完成情况统计";
        String sheetName = "sheet1";
        String[] headers = {"日期", "排班情况", "班组名称", "巡检人员", "任务名称", "线路类别", "巡检时间段", "实际巡检用时", "巡检结果"};
        String[] columns = {"startDateStr", "shiftName", "teamName", "executor", "taskName", "lineType", "time", "minuteStr", "result"};
        try {
            exportExcel.exportExcel(fileName, sheetName, headers, columns, list, response);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RRException(RRExceptionEnum.EXPORT_FAIL);
        }
    }

    @Override
    public void exportEveryTeam(HttpServletResponse response, Map<String, Object> params) {


        ExportExcel exportExcel = new ExportExcel();

        params.put("limit", "10000000");

        PageUtils pageUtils = queryInsEveryTeam(params);
        List list = pageUtils.getList();
        String fileName = "每班巡检完成情况统计";
        String sheetName = "sheet1";
        String[] headers = {"日期", "排班情况", "班组名称", "任务名称", "线路类别", "巡检时间段", "实际巡检用时", "巡检结果"};
        String[] columns = {"dateStr", "shiftName", "teamName", "taskName", "lineType", "time", "minuteStr", "result"};
        try {
            exportExcel.exportExcel(fileName, sheetName, headers, columns, list, response);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RRException(RRExceptionEnum.EXPORT_FAIL);
        }
    }

    @Override
    public PageUtils queryEverydayTotal(Map<String, Object> params) {

        Page<InsEveryTeamReport> page = new Query<InsEveryTeamReport>(params).getPage();
        List<InsEveryTeamReport> insEveryTeamReports = baseMapper.queryEverydayTotal(page, params);

        insEveryTeamReports.forEach(e -> {
            if (Optional.ofNullable(e.getMinutes()).isPresent()) {
                e.setMinuteStr(minute2hourStr(e.getMinutes(), true));
            } else {
                e.setMinuteStr(0 + "小时" + 0 + "分钟");
            }
        });

        page.setRecords(insEveryTeamReports);

        return new PageUtils(page);
    }

    @Override
    public DoubleInfo<Integer, Integer> queryEverydayInsCase(Map<String, Object> params) {
        return baseMapper.queryEverydayInsCase(params);
    }

    private String minute2hourStr(int minutes, boolean en) {

        if (minutes == 0) {
            if (en) {
                return 0 + "h" + 0 + "m";
            } else {
                return 0 + "小时" + 0 + "分钟";
            }
        }

        String hourStr = "小时";

        String minuteStr = "分钟";

        if (en) {
            hourStr = "h";
            minuteStr = "m";
        }
        int hours = (int) Math.floor(minutes / 60);
        int minute = minutes % 60;
        return hours + hourStr + minute + minuteStr;
    }
}
